﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace THO7AlgoritmTimerApplication
{
    public partial class MainForm : Form
    {
        List<VisionAlgorithm> AlgorithmList = new List<VisionAlgorithm>();
        List<VisionAlgorithm> NoiseList = new List<VisionAlgorithm>();
        Stopwatch stopWatch;
        Queue<List<object>> algoritmQueue;


        private Bitmap inputImage;
        private Bitmap outputImage;

        public Bitmap OutputImage
        {
            get { return outputImage; }
            set
            {
                outputImage = value;
                OutputPictureBox.Image = value;
            }
        }

        public MainForm()
        {
            InitializeComponent();
            AlgorithmList.Add(new VisionAlgorithm_Median("Median Filter not working"));
            AlgorithmList.Add(new VisionAlgorithm_MedianL("Median Working"));
            AlgorithmList.Add(new VisionAlgorithm_Binair("binair test"));
            //Insert new Algorithms here
            /*          ^
            *          /|\
            *           |
            */


            foreach (VisionAlgorithm vA in AlgorithmList)
            {
                AlgoListBox.Items.Add(vA.Name);
            }
            algoritmQueue = new Queue<List<object>>();
        }

        private void openPictureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openImage();
        }

        private void openImage()
        {
            OpenFileDialog oFD = new OpenFileDialog();
            oFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            oFD.Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.PNG;)|*.BMP;*.JPG;*.JPEG;*.PNG;";
            oFD.FilterIndex = 1;
            oFD.RestoreDirectory = true;
            if (oFD.ShowDialog() == DialogResult.OK)
            {
                String CurrentFileName = Path.GetFullPath(oFD.FileName);
                inputImage = new Bitmap(CurrentFileName);
                InputPictureBox.Image = inputImage;
            }
           
        }

        private void AlgoListBox_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void AlgoButton_Click(object sender, EventArgs e)
        {

            if (inputImage != null)
            {
                try
                {
                    
                        InfoLabel.Text = "";
                        int i = 0;
                        foreach (VisionAlgorithm vA in AlgorithmList)
                        {
                            if (AlgoListBox.GetItemChecked(i))
                                algoritmQueue.Enqueue(new List<object> { vA, inputImage, 1 });
                            i++;
                        }
                        runQueuedAlgorithms();
                    

                }
                catch 
                {
                    InfoLabel.Text += "Can't run that number of times\n";
                }
            }

        }

        private bool runQueuedAlgorithms()
        {
            if (algoritmQueue.Count > 0)
            {
                List<object> algArgs = algoritmQueue.Dequeue();
                InfoLabel.Text += "Start running " + ((VisionAlgorithm)(algArgs.ElementAt(0))).Name + "...\n";
                startAlgThread(algArgs);
                return true;
            }
            return false;
        }

        private void OutputPictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                Form ipForm = new ImagePreviewForm(new Bitmap(OutputPictureBox.Image));
                ipForm.Show();
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void OutputToInputButton_Click(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                inputImage = new Bitmap(OutputPictureBox.Image);
                InputPictureBox.Image = inputImage;
                OutputPictureBox.Image = null;
            }
        }


        private void ClearButton_Click(object sender, EventArgs e)
        {

            InfoLabel.Text = "";
        }

        private void backgroundAlgorithmWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }
            else if (e.Cancelled)
            {
                InfoLabel.Text += "...Cancelled\n";
            }
            else
            {
                double elapsedms = Convert.ToDouble(stopWatch.ElapsedMilliseconds);
                //double average = elapsedms / Convert.ToDouble(textBoxRuns.Text);

                InfoLabel.Text += e.Result + ", took: " + elapsedms + " ms\n"; // over " + textBoxRuns.Text + " times\n";
                //InfoLabel.Text += "==> average: " + average + "ms\n";
                OutputPictureBox.Image = outputImage;
                if (checkBoxSaveOutputImages.Checked)
                {
                    outputImage.Save(e.Result.ToString() + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
            if (!runQueuedAlgorithms())
            {
                DateTime current = DateTime.Now;
                String curStr = current.ToString("yyyy-MM-dd__HH-mm-ss");
                String fileName = curStr + "_results.txt";
                FileStream fs = new FileStream(fileName, FileMode.Create);
                StreamWriter outfile = new StreamWriter(fs, Encoding.UTF8);
                outfile.Write(InfoLabel.Text.ToString());
                outfile.Flush();
                outfile.Close();
                fs.Close();

                EnableAllInputs(true);

                //MessageBox.Show("Done...\nResults saved to: " + fileName);
            }
        }

        private void backgroundAlgorithmWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            System.ComponentModel.BackgroundWorker worker;
            worker = (System.ComponentModel.BackgroundWorker)sender;
            List<object> argList = (List<object>)e.Argument;
            VisionAlgorithm visAlg = (VisionAlgorithm)argList.ElementAt(0);
            Bitmap InputImage = (Bitmap)argList.ElementAt(1);
            int numberOfRuns = (int)argList.ElementAt(2);
            stopWatch.Start();
            try
            {

                for (int i = 1; i < numberOfRuns; i++)
                {
                    visAlg.DoAlgorithm(InputImage);
                }
                outputImage = visAlg.DoAlgorithm(InputImage);
                e.Result = visAlg.Name + " finished successfully";
            }
            catch 
            {
                e.Cancel = true;
            }
            finally
            {
                stopWatch.Stop();
            }

        }

        private void EnableAllInputs(bool state)
        {
            openPictureToolStripMenuItem.Enabled = state;
            AlgoButton.Enabled = state;
            AlgoListBox.Enabled = state;
            OutputToInput.Enabled = state;
            InputPictureBox.Enabled = state;
        }

        private void startAlgThread(List<object> argList)
        {
            stopWatch = new Stopwatch();
            EnableAllInputs(false);
            backgroundAlgorithmWorker.RunWorkerAsync(argList);
        }



        private void noise_Button_Click(object sender, EventArgs e)
        {
            if (inputImage != null)
            {
                if (saltPepper_checkBox.Checked)
                {
                    VisionAlgorithm_SaltAndPepper visAlg = new VisionAlgorithm_SaltAndPepper("salt");
                    visAlg.Intensity = Convert.ToInt32(Level_textBox.Text);
                    Bitmap noiseImage = visAlg.DoAlgorithm(inputImage);
                    OutputImage = noiseImage;
                    InfoLabel.Text += "Added noise at level " + Level_textBox.Text + "...\n";
                }
            }
        }

        private void InputPictureBox_Click(object sender, EventArgs e)
        {

        }

   







    }
}
